﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Heap
{
    public abstract class Key
    {
        public virtual int Score
        {
            get;
            set;
        }
    }

    public class CourseKey : Key
    {
        public bool Lec;
        public bool Tut;
        public bool Lab;

        public override int Score
        {
            get { return Convert.ToInt32(Lec) + Convert.ToInt32(Tut) + Convert.ToInt32(Lab); }
        }
    }

    public class ScheduleKey : Key
    {
        public CourseKey[] m_Courses;

        public ScheduleKey(int _NumberOfCourses)
            : base()
        {
            this.m_Courses = new CourseKey[_NumberOfCourses];
        }

        public override int Score
        {
            get
            {
                int score = 0;
                foreach (CourseKey c in m_Courses)
                {
                    score += c.Score;
                }
                return score;
            }
        }
    }




    public abstract class ConstraintKey
    {
        #region Data
        protected Key[] m_Keys;
        protected int m_CompareType;
        #endregion

        public ConstraintKey(int _Type)
        {
            this.m_CompareType = _Type;
        }

        public abstract int CompareTo(ConstraintKey obj);

        #region Accessors
        public virtual Key this[int i]
        {
            get{return null;}
            set { ;}
        }

        public virtual int TotalScore
        {
            get { return 0 ;}
        }

        public int CompareType
        {
            get { return this.m_CompareType; }
        }
        #endregion
    }

    public class ScheduleConstraintKey : ConstraintKey
    {
        #region Data
        private CourseConstraintKey[] m_CoursesConstraintKeys;
        #endregion

        public ScheduleConstraintKey(int _NumberOfCourses, int _Type)
            : base(_Type)
        {
            this.m_CoursesConstraintKeys = new CourseConstraintKey[_NumberOfCourses];
        }

        public override int CompareTo(ConstraintKey obj)
        {
            ScheduleConstraintKey Obj = (ScheduleConstraintKey)obj;

            if (m_CompareType == 0)
            {
                if (this.TotalScore < obj.TotalScore)
                    return -1;
                else if (this.TotalScore == obj.TotalScore)
                    return 0;
                else
                    return 1;
            }
            else
            {

                for (int i = 0; i < this.m_CoursesConstraintKeys.Length; i++)
                {
                    if (this.m_CoursesConstraintKeys[i].TotalScore < Obj[i].TotalScore)
                    {
                        return -1;
                    }
                    else if (this.m_CoursesConstraintKeys[i].TotalScore > Obj[i].TotalScore)
                    {
                        return 1;
                    }
                }

                return 0;
            }
        }

        #region Accessors
        public new ConstraintKey this[int i]
        {
            get { return this.m_CoursesConstraintKeys[i]; }
            set { this.m_CoursesConstraintKeys[i] = (CourseConstraintKey)value; }
        }

        public override int TotalScore
        {
            get
            {
                int TotalScore = 0;
                foreach (CourseConstraintKey constraintkey in this.m_CoursesConstraintKeys)
                {
                    TotalScore += constraintkey.TotalScore;
                }
                return TotalScore;
            }
        }
        #endregion
    }

    public class CourseConstraintKey : ConstraintKey
    {
        #region Data

        #endregion

        public CourseConstraintKey(int _NumberOfConstraints, int _Type)
            : base(_Type)
        {
            this.m_Keys = new CourseKey[_NumberOfConstraints];
        }

        public override int CompareTo(ConstraintKey obj)
        {
            if (m_CompareType == 0)
            {
                if (this.TotalScore < obj.TotalScore)
                    return -1;
                else if (this.TotalScore == obj.TotalScore)
                    return 0;
                else
                    return 1;
            }
            else
            {

                for (int i = 0; i < this.m_Keys.Length; i++)
                {
                    if (this.m_Keys[i].Score < obj[i].Score)
                    {
                        return -1;
                    }
                    else if (this.m_Keys[i].Score > obj[i].Score)
                    {
                        return 1;
                    }
                }

                return 0;
            }
        }

        #region Accessors
        public override int TotalScore
        {
            get
            {
                int count = 0;

                foreach (Key cons in this.m_Keys)
                {
                    count += cons.Score;
                }

                return count;
            }

        }

        public override Key this[int i]
        {
            get { return this.m_Keys[i]; }
            set { this.m_Keys[i] = value; }
        }

        #endregion
    }
}
